\section{Tutorials}
\label{sec:tut}

\subsection{Start from the minimal: a Solo node}
\label{sec:minimal}
\emoji{parrot} : What's the minimal example of \Wch{} ?

\emoji{turtle} : You can start a node in \cola{Solo} mode. This is useful if you
want to familiarize yourself with the API, such as how to send transactions.
It's also good for testing smart contracts.

\begin{simplesh}
wch --port 7777 # start a node on port 7777 in Solo mode
\end{simplesh}

Now we have no blocks yet
\begin{simplesh}
curl http://localhost:7777/get_latest_Blk # []
\end{simplesh}

\subsubsection{Deploy an Evm contract}
To deploy an Evm contract, try:
\begin{simplesh}
txs='[
  {"from" : "01",
   "to" : "",
   "data" : "608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806360fe47b11461003b5780636d4ce63c14610057575b600080fd5b610055600480360381019061005091906100c3565b610075565b005b61005f61007f565b60405161006c91906100ff565b60405180910390f35b8060008190555050565b60008054905090565b600080fd5b6000819050919050565b6100a08161008d565b81146100ab57600080fd5b50565b6000813590506100bd81610097565b92915050565b6000602082840312156100d9576100d8610088565b5b60006100e7848285016100ae565b91505092915050565b6100f98161008d565b82525050565b600060208201905061011460008301846100f0565b9291505056fea2646970667358221220271e30d641d99bedebb5450b18efe8b67269cf688a15386162d4c2ff7072a8af64736f6c63430008130033",
   "nonce" : 123
  }
]'
e=http://localhost
curl --data $txs $e:7777/add_txs
\end{simplesh}
The contract is compiled using
\begin{simplesh}
solc hi.sol --bin
\end{simplesh}
from a \texttt{hi.sol} file:
\begin{simplesol}
  // SPDX-License-Identifier: GPL-3.0
  pragma solidity >=0.4.16 <0.9.0;

  contract SimpleStorage {
    uint storedData;

    function set(uint x) public {
      storedData = x;
    }

    function get() public view returns (uint) {
      return storedData;
    }
  }
\end{simplesol}

This should return the transaction hash and the deployed address which is
something like
\begin{simplejs}
[
    {
        "hash": "b06b89b665df6f7ff1be967faf9a0601f71c0a3cdb8250c48fe7fcc663b18d1b",
        "deployed_address": "0000000000000000000000000000000064d05d1b"
    }
]
\end{simplejs}

\subsubsection{Invoke an Evm Contract}
Let's \texttt{set(123)} (invoke the method \texttt{set} with the argument 123).
The data is the Ethereum ABI encoding of the method signature and the argument.
\begin{simplesh}
$deployed_addr=0000000000000000000000000000000064d05d1b
txs="[{
  \"from\" : \"01\",
  \"to\" : \"$deployed_addr\",
   \"data\" : \"60fe47b1000000000000000000000000000000000000000000000000000000000000007b\",
   \"nonce\" : 125
  }]"
curl --data $txs $e:7778/add_txs
\end{simplesh}

Then \texttt{get()} (invoke the method \texttt{get}).
\begin{simplesh}
txs="[{
  \"from\" : \"01\",
  \"to\" : \"$deployed_addr\",
  \"data\" : \"6d4ce63c\",
  \"nonce\" : 126
}]"

curl --data $txs $e:7777/add_txs
# [{"hash":"f192381aa197b851870e98fc515414c51d2311fea7e5bc01c16dceb6a7fed3d9"}]
\end{simplesh}

The result of method invocation is stored in the \cola{transaction receipt}, we
can get it by
\begin{simplesh}
curl $e:7777/get_receipt?hash=f192381aa197b851870e98fc515414c51d2311fea7e5bc01c16dceb6a7fed3d9

# The result of get() is 0x7b = 123 as expected
# {"ok":true,"result":"000000000000000000000000000000000000000000000000000000000000007b"}
\end{simplesh}

You can retrieve the transaction by looking at the latest block
\begin{simplesh}
curl http://localhost:7777/get_latest_Blk # [{
...
"txs": [{...your transaction should be here...}]
}]
\end{simplesh}

Or using the \texttt{get\_tx} method:
\begin{simplesh}
curl http://localhost:7777/get_tx?hash=f192381aa197b851870e98fc515414c51d2311fea7e5bc01c16dceb6a7fed3d9
\end{simplesh}


\subsection{The simplest transaction: Pure Data transaction}
\emoji{parrot} : What if I just want to store some data on the blockchain? For
example just a pdf. Is there a simple way to do that?

\emoji{turtle} : In that case, \Wch{} has \cola{pure data transaction}.

Suppose we have an \Wch{} endpoint at \texttt{http://localhost:7777} (as can be
done in \cref{sec:minimal}), we can send a pure data transaction by
\begin{simplesh}
txs="[{
  \"from\" : \"01\",
  \"to\" : \"\",
  \"type\" : \"data\",
  \"data\" : \"aaa\",
  \"nonce\" : 123
}]"

curl --data $txs $e:7777/add_txs
\end{simplesh}

When \Wch{} encounters a transaction of this type when executing a block, it
simply write \texttt{ok} in its transaction receipt, no VM is initialized.

\begin{weakBox}
  \emoji{turtle} : In other blockchain, the simplest transaction is usually a
  ``transfer'' transaction. But there's no ``currency'' in \Wch{}. So no
  built-in transfer transaction. However, you can always implement one using
  smart contract.
\end{weakBox}

\subsection{Python Contract}
\label{sec:pyvm}

\Wch{} allows you to write smart contracts in Python.

Deploy a Python contract:

Suppose we have \texttt{/tmp/tmp.py}:
\begin{simplepy}
from typing import Any
def hi(_storage: dict[str, Any], y : int) -> int:
    _storage["x"] = _storage.get("x", 1) + y
    return _storage["x"]
\end{simplepy}
Then to deploy the contract, we can use:
\begin{simplesh}

txs='[{"from" : "01","to" : "",
 "data" : "@/tmp/tmp.py",
 "nonce" : 123,
 "type" : "python"
}]'
# jq converts the text file into valid jsonstring

e=http://localhost
curl --data $txs $e:7777/add_txs
# => "deployed_address": "0000000000000000000000000000000064d05d1b"
\end{simplesh}

Invoke a Python contract:

Suppose we have \texttt{/tmp/tmp.json}:
\begin{simplejs}
{
        "method" : "hi",
        "args" : {"y" : 122}
}
\end{simplejs}
Then to invoke the contract, we can use:
\begin{simplesh}

txs='[{
    "from" : "01",
    "to" : "'"$da"'",
    "data" : "@/tmp/tmp.json",
    "nonce" : 124,
    "type" : "python"
}]'
e=http://localhost
curl --data $txs $e:7777/add_txs
# => "hash": "c63fce1da4f0a30c0ae6c8ce332286f188d71dc13638beca74fb5939c5a79ec8",

# get the result
curl "$e:7777/get_receipt?hash=c63fce1da4f0a30c0ae6c8ce332286f188d71dc13638beca74fb5939c5a79ec8"
# {"ok":true,"result": 123}
\end{simplesh}

\emoji{parrot} : Hey, the python contract is much friendlier!
\emoji{turtle} : Yeah, it's designed to be so. To learn more,
see \cref{sec:how-to-py}.

\subsection{Start a Raft Cluster}
\label{sec:tut-raft}

To start a minimal three-node Raft cluster, open three terminals and run the following
\begin{simplesh}
# terminal of node 1
wch --port 7777 --consensus Raft --Raft.node-list localhost:7778 localhost:7779

# terminal of node 2
wch --port 7778 --consensus Raft --Raft.node-list localhost:7777 localhost:7779

# terminal of node 3
wch --port 7779 --consensus Raft --Raft.node-list localhost:7777 localhost:7778
\end{simplesh}

Wait until a primary node is elected. Now, we can send a transaction to the any
node:

\begin{simplesh}
txs="[{
  \"from\" : \"01\",
  \"to\" : \"\",
  \"type\" : \"data\",
  \"data\" : \"aaa\",
  \"nonce\" : 123
}]"

curl --data $txs $e:7777/add_txs
\end{simplesh}

\subsection{Start a Pbft Cluster}
\label{sec:tut-pbft}

To start a minimal four-node Pbft cluster, open three terminals and run the
following:
\begin{simplesh}
# terminal of node 1
wch --port 7777 --consensus Rbft --Bft.node-list localhost:7777 localhost:7778 localhost:7779 localhost:7780

# terminal of node 2
wch --port 7778 --consensus Rbft --Bft.node-list localhost:7777 localhost:7778 localhost:7779 localhost:7780

# terminal of node 3
wch --port 7779 --consensus Rbft --Bft.node-list localhost:7777 localhost:7778 localhost:7779 localhost:7780

# terminal of node 4
wch --port 7780 --consensus Rbft --Bft.node-list localhost:7777 localhost:7778 localhost:7779 localhost:7780
\end{simplesh}

If you are using the above method, make sure all the commands are run within the
same epoch, which is usually 8 seconds. In this case, all nodes are considered
as ``existing nodes''. Alternatively, \Wch{} provides a way to dynamically add
new nodes to existing PBFT cluster. To do that, we can do:
\begin{simplesh}
# terminal of node 1
wch --port 7777 --consensus Rbft --Bft.node-list localhost:7777  # start a one-node cluster

# terminal of node 2
wch --port 7778 --consensus Rbft --Bft.node-list localhost:7777  
# try join the cluster, existing nodes = {n1}

# the node2 will join the cluster after the next view-change, after that we can 
# add a new node

# terminal of node 3
wch --port 7779 --consensus Rbft --Bft.node-list localhost:7777 localhost:7778
# try join the cluster, existing nodes = {n1, n2}

\end{simplesh}

This is in fact the recommended way to start a PBFT cluster. Because the
maintainers won't need to worry about the timming of the commands.

\subsection{Production Cryptography}
\label{sec:tut-serious-crypto}

So far we have been using \Wch{} without any serious cryptography. For example,
no key was needed to sign the transactions, and no certificates were involved
when the nodes communicate. This is fine (and good) for testing and development,
but in production, we need to use real cryptography. In particular, we need to
\begin{enumerate}
\item Verify a node's identity with a certificate before allowing it to join the
  cluster.
\item Sign the transactions with a private key. The key pair identifies the
  sender of the transaction.
\end{enumerate}

These two requirements are actually decoupled in \Wch{}. We show how to do both now.

\subsubsection{Secure the cluster}
To start a ``secure cluster'', we need to do the following
\begin{enumerate}
\item Generate a key pair for CA.
\item Generate a key pair for each node.
\item Sign the node's public key with the CA's private key to get a certificate.
\end{enumerate}

\Wch{} provides tools to do these:
\begin{simplesh}
# 1. generate a key pair for CA, save them to ca-pk.pem and ca-sk.pem
wch toolbox new-keypair ca-pk.pem ca-sk.pem

# 2. generate a key pair for node 1,2,3
wch toolbox new-keypair n1-pk.pem n1-sk.pem
wch toolbox new-keypair n2-pk.pem n2-sk.pem
wch toolbox new-keypair n3-pk.pem n3-sk.pem

# 3. sign the public key of node 1,2,3 with the CA's private key to create a certificate 
wch toolbox do-sign ca-sk.pem n1-pk.pem n1.cert
wch toolbox do-sign ca-sk.pem n2-pk.pem n2.cert
wch toolbox do-sign ca-sk.pem n3-pk.pem n3.cert
\end{simplesh}

Now to tell \Wch{} this rather complicated setup, we need to provide a so-called
``peer-json'', which looks like
\begin{simplejs}
{
    "localhost:7777" : {"pk_pem_file": "/path/to/n1-pk.pem", "cert_file": "/path/to/n1.cert"},
    "localhost:7778" : {"pk_pem_file": "/path/to/n2-pk.pem", "cert_file": "/path/to/n2.cert"},
    "localhost:7779" : {"pk_pem_file": "/path/to/n3-pk.pem", "cert_file": "/path/to/n3.cert"}
}
\end{simplejs}

Save it to \texttt{peer.json} and let's try start a PBFT cluster:
\begin{simplesh}
# terminal of node 1
wch --port 7777 --consensus Rbft --Bft.node-list localhost:7778 localhost:7779 \
    --without-crypto no \
    --crypto.ca_public_key_pem_file /path/to/ca-pk.pem \
    --crypto.peer_json_file_or_string @/path/to/peer.json \
    --crypto.node_secret_key_pem_file /path/to/n1-sk.pem
    --crypto.node_cert_file /path/to/n1.cert

# terminal of node 2
wch --port 7778 --consensus Rbft --Bft.node-list localhost:7777 localhost:7779 \
    --without-crypto no \
    --crypto.ca_public_key_pem_file /path/to/ca-pk.pem \
    --crypto.peer_json_file_or_string @/path/to/peer.json \
    --crypto.node_secret_key_pem_file /path/to/n2-sk.pem
    --crypto.node_cert_file /path/to/n2.cert

# terminal of node 3
wch --port 7779 --consensus Rbft --Bft.node-list localhost:7777 localhost:7778 \
    --without-crypto no \
    --crypto.ca_public_key_pem_file /path/to/ca-pk.pem \
    --crypto.peer_json_file_or_string @/path/to/peer.json \
    --crypto.node_secret_key_pem_file /path/to/n3-sk.pem
    --crypto.node_cert_file /path/to/n3.cert
\end{simplesh}

Note that the \texttt{--without-crypto no} is necessary to enable the
certificate verification of cluster. Now we can just send transactions as usual.

\subsubsection{Secure the Transaction}
\label{sec:secure-tx}

So far, we can just send transactions without any signature. This means we can
just claim to be any account and send transactions. This is good for testing,
but no good for production. In production, we need to first generate a key pair
for our account, and sign the transaction with the private key. To enable such
transaction verification, we need to start the node differently. \Wch{} offers
three types of transaction verification mode:
\begin{enumerate}
\item \texttt{test tx-mode}: no verification is done. This is the default mode.
\item \texttt{public tx-mode}: any public keys are allowed to send transactions.
\item \texttt{ca tx-mode}: only the public keys signed by a CA are allowed to send
  transactions.
\end{enumerate}

We are gonna demonstrate this using a Solo node, but the same can be applied to
Raft and PBFT nodes.

\cola{To start a Solo node with \texttt{public tx-mode}}, we can do
\begin{simplesh}
wch --port 7777 --light-exe --tx-mode-serious public
\end{simplesh}

Now to send a transaction, we first need to generate a key pair, that represents
our account. We can do this by
\begin{simplesh}
wch toolbox new-keypair my-pk.pem my-sk.pem
\end{simplesh}

Next we need to sign the transaction with the private key. To do that, we first
our transaction in a file, say \texttt{tx-unsigned.json}:
\begin{simplejs}
[{"type" : "data", "from" : "01", "to" : "", "data" : "hi", "nonce" : 123}]
\end{simplejs}
Then we can sign the transaction by
\begin{simplesh}
wch toolbox tx-sign-no-crt tx-unsigned.json my-sk.pem tx-signed.json
\end{simplesh}

The signed transaction is now in \texttt{tx-signed.json}:
\begin{simplejs}
[
  {
    "type": "data",
    "from": "01",
    "to": "",
    "data": "hi",
    "nonce": 123,
    "signature": "ed70765d68dd2cadd5f728cf6c2eed40803248e650bd81728ea9cd4f31e340dff8139b54be520dd6f2b9568e17e68ac3820e46dfc4e1ad5cdf915b115e503402",
    "pk_pem": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAT47M3UrUIEwqtPzKox/9Ar5ouCxL1l8SjYbGHjBzEfk=\n-----END PUBLIC KEY-----\n"
  }
]
\end{simplejs}

Note that when the \texttt{pk\_pem} field is present, the \texttt{from} field is ignored.

Next we can send the transaction as usual:
\begin{simplesh}
curl --data @tx-signed.json http://localhost:7777/add_txs
\end{simplesh}

\cola{To start a Solo node with \texttt{ca tx-mode}}, we first need to generate
a CA, which is simply a key pair. We can do this by using:
\begin{simplesh}
capk=./ca-pk.pem
cask=./ca-sk.pem
wch toolbox new-keypair $capk $cask
\end{simplesh}

Next, we can start the chain in \texttt{ca tx-mode} using the \texttt{ca@<key>}
syntax:
\begin{simplesh}
wch --port 7777 --light-exe --tx-mode-serious ca@$capk
\end{simplesh}

Next, we can generate a key pair for our account:
\begin{simplesh}
# create an account
pk=./acn-pk.pem
sk=./acn-sk.pem
wch toolbox new-keypair $pk $sk
\end{simplesh}

Next we issue a certificate for the account using the \texttt{wch toolbox
  sign-pk} command:
\begin{simplesh}
# sign the account with the ca's secret key
cask=./ca-sk.pem
crt=./acn-crt.bin
wch toolbox sign-pk $cask $pk $crt
\end{simplesh}

Now we are ready to send a Transaction. Here we need a two-step process:
\begin{enumerate}
\item Prepare the transation to be signed
\item Sign the transaction with our secret key
\end{enumerate}
\begin{simplesh}
txf=./tx-pre.json
txf2=./tx-post.json
# 1. prepare the transaction to be signed
echo '[{"type" : "data", "to" : "", "data" : "hi", "nonce" : 123}]' > $txf
# 2. sign the tx
wch toolbox tx-sign $txf $sk $crt $txf2
\end{simplesh}

Finally we can send the transaction as usual:
\begin{simplesh}
curl --data @$txf2 http://localhost:7777/add_txs
\end{simplesh}



% Local Variables:
% TeX-engine: luatex
% TeX-command-extra-options: "-shell-escape"
% TeX-master: "m.tex"
% TeX-parse-self: t
% TeX-auto-save: t
% End: